package com.example;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;

public class UdpServer {

    private final Bootstrap bootstrap;
    private final NioEventLoopGroup acceptGroup;
    private Channel channel;

    public void start(int port) throws Exception {
        try {
            channel = bootstrap.bind(port).sync().channel();
            System.out.println("UdpServer start success" + port);
            channel.closeFuture().await();
        }
        finally {
            acceptGroup.shutdownGracefully();
        }
    }

    public Channel getChannel() {
        return channel;
    }

    public static UdpServer getInstance() {
        return UdpServerHolder.INSTANCE;
    }

    private static final class UdpServerHolder {

        static final UdpServer INSTANCE = new UdpServer();
    }

    private UdpServer() {
        bootstrap = new Bootstrap();
        acceptGroup = new NioEventLoopGroup();
        bootstrap.group(acceptGroup)
                 .channel(NioDatagramChannel.class)
                 .option(ChannelOption.SO_BROADCAST, true)
                 .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                 .option(ChannelOption.SO_RCVBUF, 1024 * 1024 * 10)
                 .handler(new ChannelInitializer<NioDatagramChannel>() {
                     @Override
                     protected void initChannel(NioDatagramChannel ch)
                         throws Exception {
                         ChannelPipeline pipeline = ch.pipeline();
                         pipeline.addLast(new UdpServerHandler());
                     }
                 });
    }
}
